#pragma once

// #include "Channel.h"
// #include <Log.h> //就比如这个log，就可以放到源文件中去，
#include <iostream>
#include <cstdint>
#include <functional>
#include <vector>
#include <memory>
#include <unordered_map>
#include <string.h>
#include <sys/timerfd.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>

using Task_func = std::function<void()>;
using Release_fun =std::function<void()>;
namespace muduo{
    // 定时器对象

    // 前置声明
    class Channel;
    
    class TimerTask
    {

    private:
        /*
        定时器的id
        触发定时器的时间
        定时器触发的函数
        设置定时任务是否被触发 -false代表触发 -true代表不触发
        设置销毁定时任务时执行的函数（在时间轮中消除timertask）
        */
        uint64_t _id;
        uint32_t _timeout;
        Task_func _task_cb;
        bool _cancel;
        Release_fun _release;
    public:
        TimerTask(uint64_t id,uint32_t timeout,const Task_func& task_cb);
        ~TimerTask();
        void SetRelease(Release_fun release);
        void SetCancel();
        uint32_t Get_timeout();
    };
    // 时间轮
    class EventLoop;
    class TimerWheel
    {   
        using PtrTask = std::shared_ptr<TimerTask>;
        using WeakTask = std::weak_ptr<TimerTask>;
    private:
        /*
        滴答指针
        时间轮的容量-对用最大延迟时间
        时间轮结构声明
        管理的所有TimerTask对象
        */
        int _tick;
        int _capacity;
        std::vector<std::vector<PtrTask>> _wheel;
        // 使用weak_ptr管理的目的是，weak不增加引用计数并且可以提供给shared_ptr进行复制
        std::unordered_map<uint64_t, WeakTask> _timers;

        EventLoop* _loop;
        int _timerfd;
        Channel* _timerChannel; 
    private:
        // 移除定时器
        void RemoveTimer(uint64_t id);
        // 创建timerfd
        static int CreatetimerFd();
        // timerfd每次超时后触发的回调函数
        int Readtimerfd();
        // 每秒向后移动滴答指针的函数
        void RunOnTime();
        void AddTimerTaskInLoop(uint64_t id,uint32_t delay,const Task_func& task_cb);
        void TimerRefreshInLoop(uint64_t id);
        void TimerCancelInLoop(uint64_t id);
        void RunTimeTask();
    public:
        TimerWheel(EventLoop* loop);
        // 添加定时任务
        void AddTimerTask(uint64_t id,uint32_t delay,const Task_func& task_cb);
        // 更新/延迟定时任务
        void TimerRefresh(uint64_t id);      
        void TimerCancel(uint64_t id);
        // 判断是否有传入的定时器
        bool HasTimer(uint64_t id);
    };
}